package org.gwt.project.tools.cpe;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.jdt.core.ClasspathContainerInitializer;
import org.eclipse.jdt.core.IClasspathContainer;
import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.gwt.project.tools.ToolsConfig;
import org.gwt.project.tools.ToolsPlugin;
import org.gwt.project.tools.ToolsUtil;

public class Container implements IClasspathContainer {
	
	public static final String ID = ToolsPlugin.ID + ".cpe.container";
	
	public static final String DESCRIPTION = "GWT User Libraries";
	
	public static final IPath PATH = new Path(ID);
	
	private final IPath path;
	private final IJavaProject project;

	public Container(IJavaProject project) {
		this(PATH,project);
	}
	
	public Container(IPath path, IJavaProject project) {
		this.path = path;
		this.project = project;
	}

	@Override
	public IPath getPath() {
		return path;
	}	

	@Override
	public int getKind() {
		return IClasspathContainer.K_APPLICATION;
	}

	@Override
	public String getDescription() {
		return DESCRIPTION;
	}

	@Override
	public IClasspathEntry[] getClasspathEntries() {
		// Initialize
		ToolsConfig config = new ToolsConfig();
		List<IClasspathEntry> entries = new ArrayList<IClasspathEntry>();
		// Get files
		try {
			for(IResource it : members(config)) {
				// Sanity checks 
				if(it.exists() && it.isAccessible()) {
					// Get path to library copied by ToolsBuilder into this project
					IPath libPath = getDstPath(getProject(),it,config);
					// Does library exist?
					if(getProject().exists(libPath.makeRelativeTo(getProject().getLocation()))) {
						// Get path to associated source code 					
						IPath srcPath = getSrcPath(it.getLocation());
						// Does source library exist?
						IClasspathEntry entry;
						if(getProject().exists(srcPath)) {
							// Create a new exported CPE_LIBRARY type with attached source
							entry = JavaCore.newLibraryEntry(libPath, srcPath, new Path("/"), true);
						} else {
							// Create a new exported CPE_LIBRARY type (no source attached)
							entry = JavaCore.newLibraryEntry(libPath, null, null, true);
						}
				        entries.add( entry );
						
						// NOTE: This is only available from Helios and upwards (3.6+)
				        entries.addAll( Arrays.asList(JavaCore.getReferencedClasspathEntries(entry, null)) );
						
					}
				}
			}
		} catch (CoreException e) {
			// TODO: Add 'Clean Project...' problem marker
			ToolsPlugin.log("Failed to read '"+Container.DESCRIPTION+"' classpath entry definitions",e);
		}
		// Convert to array and return it
	    return entries.toArray(new IClasspathEntry[entries.size()]);	
	}
	
	public IProject getProject() {
		return project.getProject();
	}
	
	public IJavaProject getJavaProject() {
		return project;
	}
	
	private List<IResource> members(ToolsConfig config) throws CoreException {
		return ToolsUtil.getSrcLibs(getProject(), config);
	}
	
	private IPath getDstPath(IProject dst, IResource resource, ToolsConfig config) {
		// Get path to source library
		return dst.getFolder(config.getDstLib()).
				getLocation().
					append(resource.getLocation().lastSegment());
	}
	
	private IPath getSrcPath(IPath path) {
		// Get source library name
		String name = path.removeFileExtension().lastSegment() + "-src";
		// Get path to source library
		return path.removeLastSegments(1).append(name).addFileExtension(path.getFileExtension());
	}
	
//	public boolean isValid() {
//		// Initialize
//		ToolsConfig config = new ToolsConfig();
//		// Check user lib destination folder
//		return getProject().exists(new Path(config.getDstLib()));
//	}
	
	public static class Initializer extends ClasspathContainerInitializer {
		
		public Initializer() { }
	
		@Override
		public void initialize(IPath path, IJavaProject project)
				throws CoreException {
			
			Container container = new Container( path, project );
//		    if(container.isValid()) {
		        JavaCore.setClasspathContainer(
		        		path, 
		        		new IJavaProject[] {project},
		        		new IClasspathContainer[] {container}, 
		        		new NullProgressMonitor());		        
//		    } else {
//		    	// TODO: Add 'Create ...' marker to project
//		        throw ToolsPlugin.asException("Container path '" + path + "' does not exist");
//		    }			
	
		}
		
	}

}
